package br.edu.ufcg.compiladores.brasigol;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.Stack;

import org.apache.log4j.Logger;
import org.apache.log4j.spi.RootLogger;
import org.apache.log4j.xml.DOMConfigurator;

import br.edu.ufcg.compiladores.brasigol.analisador.AnalisadorLexico;
import br.edu.ufcg.compiladores.brasigol.analisador.AnalisadorSemantico;
import br.edu.ufcg.compiladores.brasigol.analisador.AnalisadorSintatico;
import br.edu.ufcg.compiladores.brasigol.erros.ErroDeAnalise;
import br.edu.ufcg.compiladores.brasigol.geracao.GeradorDeCodigo;

public class Brasigol {
	private static Logger logger = RootLogger.getLogger(Brasigol.class);
	private static final String SINTAXE_CORRETA = "java Brasigol -f <programaFonte> <programaFonte> ...";
	private static final String MSG_SINTAXE = "A sintaxe correta para a execucao do programa eh a seguinte:";
	private static final String ANALISE_SINTATICA_NORMAL = "Nenhum erro sintatico encontrado.";
	private static final String ANALISE_SEMANTICA_NORMAL = "Nenhum erro semantico encontrado.";
	private static final String QUEBRA_DE_LINHA = System.getProperty("line.separator");

	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception {
		DOMConfigurator.configure("log4j.cfg.xml");
		if (args.length < 2) {
			logger.error(MSG_SINTAXE);
			logger.error(SINTAXE_CORRETA);
			System.exit(1);
		}

		AnalisadorSintatico sintatico = new AnalisadorSintatico();
		AnalisadorSemantico semantico = new AnalisadorSemantico();
		for (int posicao =  1; posicao < args.length; posicao++) {
			File programaFonte = new File(args[posicao]);
			verificaConsistencia(programaFonte);
			String linha = "";
			String texto = "";
			BufferedReader reader = new BufferedReader(new FileReader(programaFonte));
			while ((linha = reader.readLine()) != null) {
				texto += linha + QUEBRA_DE_LINHA;
			}
			AnalisadorLexico lexico = new AnalisadorLexico(texto);
			GeradorDeCodigo gerador = new GeradorDeCodigo(programaFonte);
			semantico.setGerador(gerador);
			iniciarAnalise(programaFonte);
			try {
				sintatico.parse(lexico, semantico);
				Stack<ErroDeAnalise> pilhaDeErros = sintatico.getPilhaDeErros();
				Stack<ErroDeAnalise> pilhaDeErrosSemanticos = semantico.getPilhaDeErros();
				if (sintatico.isCorrect() && semantico.isCorrect()){ 
					logger.info(ANALISE_SINTATICA_NORMAL);
					logger.info(ANALISE_SEMANTICA_NORMAL);
					gerador.gerar();
				}
				while (!pilhaDeErros.isEmpty()) {
					logger.error(pilhaDeErros.pop());
				}
				while (!pilhaDeErrosSemanticos.isEmpty()) {
					logger.error(pilhaDeErrosSemanticos.pop());
				}
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		}
	}

	/**
	 * @param f
	 */
	private static void verificaConsistencia(File f) {
		if (!f.exists()) {
			logger.error("Arquivo " + f.getName() + " eh inexistente!");
			logger.error("Selecione um arquivo valido.");
			System.exit(1);
		}
	}

	/**
	 * @param programaFonte
	 */
	private static void iniciarAnalise(File programaFonte) {
		logger.info("Inicio do programa fonte " + programaFonte.getName());
	}
}